package ratkit;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import ratkit.parameter.RatKitParameter;
import ratkit.repast.RepastScenarioBuilder;
import repast.simphony.engine.schedule.ScheduleParameters;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RatKitTest {

	/**
	 * Default empty exception
	 */
	static class None extends Throwable {
		private static final long serialVersionUID = 1L;

		private None() {
		}
	}

	/**
	 * Optionally specify <code>expected</code>, a Throwable, to cause a test
	 * method to succeed if an exception of the specified class is thrown by the
	 * method.
	 */
	Class<? extends Throwable> expected() default None.class;

	/**
	 * Optionally specify <code>timeout</code> in milliseconds to cause a test
	 * method to fail if it takes longer than that number of milliseconds.
	 */
	long timeout() default 0L;

	/**
	 * Duration value of the test method execution..
	 * 
	 * @return
	 */
	double runUntil() default Double.MAX_VALUE;

	/**
	 * A list of test parameters.
	 * 
	 * @return a list of test parameters for the current test method.
	 */
	RatKitParameter[] parameters() default {};

	/**
	 * Scenario builder class of for the current simulation test case.
	 * 
	 * @return class of the Scenario Builder.
	 */
	Class<? extends RepastScenarioBuilder> scenarioBuilderClass();

	/**
	 * Specifies the number of objects that implement to this method to schedule
	 * this method on. The objects will be drawn randomly from a Context.
	 * Default is to schedule all instances.
	 */
	long pick() default Long.MAX_VALUE;

	/**
	 * Specifies the start time
	 */
	double start() default 1.0;

	/**
	 * Specifies the interval. If > 0, then the method is scheduled to repeat at
	 * the specified interval. Otherwise, method is scheduled for one time
	 * execution. Default is 0 meaning by default the method will only execute
	 * once.
	 */
	double interval() default 0;

	/**
	 * Priority w/r to other actions scheduled for the same tick. Default is
	 * {@code ScheduleParameters#LAST_PRIORITY}.
	 */
	double priority() default ScheduleParameters.LAST_PRIORITY;

	/**
	 * How many ticks the action can execute in the background while the tick
	 * count progresses. Default is no duration meaning the method must finish
	 * execution before the next scheduled action can execute.
	 */
	double duration() default ScheduleParameters.NO_DURATION;

	/**
	 * Whether or not to randomize the scheduling of collections of agent
	 * methods, if more than one agent is being scheduled by this annotation.
	 */
	boolean shuffle() default false;
}